package com.example.common.aspect;

import com.alibaba.fastjson.JSONObject;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.log4j.Log4j2;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * @Description: 日志切面
 * @Auther: Swain
 * @Date: 2021/1/13 14:33
 * @Version 1.0.0
 */
@Log4j2
@Aspect
@Component
public class LogAspect {

    ThreadLocal<Long> startTime = new ThreadLocal<>();

    @Pointcut("execution(public * com.example.controller.*.*(..))")
    public void apiLog() {
    }

    @Pointcut("execution(public * com.example.mapper.*.*(..))")
    public void mapperLog() {
    }

    @Before("apiLog()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
            .getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        startTime.set(System.currentTimeMillis());
        log.info(
            "【=================================== 请求处理开始 ========================================】");
        log.info("【请求地址】:" + request.getRequestURL().toString());
        log.info("【请求方式】:" + request.getMethod());
        log.info("【来源IP】:" + request.getRemoteAddr());
        log.info(
            "【请求方法】:" + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint
                .getSignature().getName());
        log.info("【请求参数】: " + JSONObject.toJSONString(joinPoint.getArgs()));
    }

    @AfterReturning(returning = "obj", pointcut = "apiLog()")
    public void doAfterReturning(Object obj) throws Throwable {
        // 处理完请求，返回内容
        log.info("【响应内容】: " + obj);
        log.info("【响应时长】: " + (System.currentTimeMillis() - startTime.get()) + "ms");
        log.info(
            "【=================================== 请求处理结束 ========================================】");
    }

    @Around("mapperLog()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        long startTime = System.currentTimeMillis();
        log.info("[Mapper方法]: " + pjp.getSignature().toString());
        log.info("[Mapper入参]: " + JSONObject.toJSONString(pjp.getArgs()));
        Object obj = pjp.proceed();
        log.info("[Mapper_sql粗略耗时]: " + (System.currentTimeMillis() - startTime) + "ms");
        return obj;
    }


}
